package org.duang.http.base;

import java.io.InputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.HttpHeaders;
import org.duang.http.auth.Signature;
import org.duang.http.common.ClientException;
import org.duang.http.common.RequestMessage;
import org.duang.http.common.ResponseMessage;
import org.duang.http.core.DefaultServiceClient;
import org.duang.http.core.HttpCallBack;
import org.duang.http.core.ServiceClient;
import org.duang.http.core.enums.HttpMethod;
import org.duang.http.core.inter.AsyncCallback;
import org.duang.http.core.inter.AsyncResult;
import org.duang.http.core.inter.ResultParser;
import org.duang.http.util.HttpUtil;
import org.duang.kit.ToolsKit;

import com.aliyun4j.utils.Tools;

public class HttpClient {

	private HttpMethod method;
	private ServiceClient client;
	private Map<String, Object> params; // 提交的参数
	private boolean security = false;
	private InputStream content;
	private URI uri;

	private final static Map<String, String> headers = new HashMap<String, String>();
	private final static Map<String, ServiceClient> serviceClients = new ConcurrentHashMap<String, ServiceClient>();
	
	public ServiceClient getClient(String url) {
		uri = HttpUtil.getHttpURI(url);
		String key = uri.getHost();
		ServiceClient client = serviceClients.get(key);
		if (ToolsKit.isEmpty(client)) {
			try{
				client = new DefaultServiceClient();
				serviceClients.put(key, client);
			} catch(ClientException ce) {
				serviceClients.remove(key);
				((DefaultServiceClient)client).close();
			}
		}
		return client;
	}

	public HttpClient(HttpMethod method, String url, Map<String, Object> params, InputStream content) {
		this.client = getClient(url);
		this.method = method;
		this.params = params;
		this.content = content;
	}

	public void setSecurity(boolean security) {
		this.security = security;
	}

	public boolean isSecurity() {
		return this.security;
	}

	private RequestMessage buildRequestMessage() {
		RequestMessage request = new RequestMessage();
		request.setMethod(method);
		request.setUrl(uri);
		
		if (security && !params.isEmpty()) {
			params.put(Signature.DUANG_SGIN_RESULT_FIELD, Signature.getSignResult(params));
		}
		request.setHeaders(getDefaultHeaders());
		//if(ToolsKit.isEmpty(params.get(HttpKit.TOKENID_FIELD))) params.put(HttpKit.TOKENID_FIELD, "tokenid_undefined");
		if(null != content){
			request.setContent(content);
			long length = 0l;
			try{
				length = Long.parseLong(content.available()+"");
			} catch(Exception e){}
			request.setContentLength(length);
		}
		if(null != params && !params.isEmpty()) request.setParams(params);
		return request;
	}

	public HttpRes send() {
		HttpCallBack<ResponseMessage> callback = new HttpCallBack<ResponseMessage>(buildResultParser(), null);
		AsyncResult<ResponseMessage> asyncResult = callback.getAsyncResult();
		client.sendRequest(buildRequestMessage(), callback);
		if(ToolsKit.isEmpty(callback) && !asyncResult.isSuccess()) return null;
		ResponseMessage message = asyncResult.getResult();
		InputStream is = null;
		final HttpRes response = new HttpRes();
		try {
			is = message.getContent();
			String result = ToolsKit.inputStream2String(is);
			response.setResult(result);
			response.setStatusCode(message.getStatusCode());
			response.setHeaders(message.getHeaders());
			response.setException(asyncResult.getException());
		} catch (Exception e) {
			response.setException(e);
		}
		callback.close();
		return response;
	}

	public void send(AsyncCallback<ResponseMessage> callback) {
		HttpCallBack<ResponseMessage> cb = new HttpCallBack<ResponseMessage>(buildResultParser(), callback);
		client.sendRequest(buildRequestMessage(), cb);
	}

	private ResultParser<ResponseMessage> buildResultParser() {
		return new ResultParser<ResponseMessage>(){
			@Override
			public ResponseMessage parse(ResponseMessage responseMessage) throws Exception {
				return responseMessage;
			}
		};
	}
	
	private Map<String, String> getDefaultHeaders() {
		if(headers.isEmpty()){
			headers.put(HttpHeaders.ACCEPT_CHARSET, HttpUtil.UTF8_CHARSET);
			headers.put(HttpHeaders.USER_AGENT,  HttpUtil.createUserAgent());
		}
		if(security) {
			headers.put(HttpHeaders.AUTHORIZATION, HttpUtil.createAuthorizAtionSignKey());
		}
		headers.put(HttpHeaders.DATE, System.currentTimeMillis()+"");
		return headers;
	}
}
